#include "gtkutils.h"

void objectUnref(gpointer obj) {
    g_object_unref(obj);
}

// // ------------------------------------ Signal Connection
// typedef void (*signalFunc)(GtkWidget *widget, gpointer user_data);
// typedef void (*signalSwappendFunc)(gpointer user_data, GtkWidget *widget);
// #define createSignalFunc(func) static void func(GtkWidget *widget, gpointer user_data)
// #define createSignalSwappedFunc(func) static void func(gpointer user_data, GtkWidget *widget)
// #define createSignalObjectFunc(func, type) static void func(GtkWidget *widget, type *user_data)
// #define createSignalSwappedObjectFunc(func, type) static void func(type *user_data, GtkWidget *widget)

// Universal
void connectTargetAction(gpointer target, gpointer source, gchar *action, signalFunc call_action){
    g_signal_connect(source, action, G_CALLBACK(call_action), target);
}
void connectTargetSwappedAction(gpointer target, gpointer source, gchar *action, signalSwappendFunc call_action){
    g_signal_connect_swapped(source, action, G_CALLBACK(call_action), target);
}

// ---- Custome 
// Button
void connectButtonClickAction(gpointer target, GtkButton* button, signalFunc clicked_action) {
    connectTargetAction(target, button, "clicked", clicked_action);
}
void connectButtonClickSwappedAction(gpointer target, GtkButton* button, signalSwappendFunc clicked_swap_action) {
    connectTargetSwappedAction(target, button, "clicked", clicked_swap_action);
}
void connectButtonClickAndSwappedAction(gpointer target, GtkButton* button, signalFunc clicked_action, signalSwappendFunc clicked_swap_action) {
    connectButtonClickAction(target, button, clicked_action);
    connectButtonClickSwappedAction(target, button, clicked_swap_action);
}
GtkButton* createButtonAction(gpointer target, const gchar *label, signalFunc clicked_action) {
    GtkButton *button = createButton(label);
    connectButtonClickAction(target, button, clicked_action);
    return button;
}
GtkButton* createButtonSwappedAction(gpointer target, const gchar *label, signalSwappendFunc clicked_swap_action) {
    GtkButton *button = createButton(label);
    connectButtonClickSwappedAction(target, button, clicked_swap_action);
    return button;
}


// ------------------------------------ Widgets Creator
// GtkWidget* createWidgets((GtkWidget*) widget_type, gchar *label) {}
GtkApplication * createApplication(const gchar *label, GApplicationFlags flags) {
    return gtk_application_new(label, flags);
}
GtkApplication * createApplicationConnectActivate(const gchar *label, GApplicationFlags flags, gpointer activate) {
    GtkApplication* app = createApplication(label, flags);
    connectTargetAction(NULL, app, "activate", activate);
    return app;
}
// App run
gint runApplication(gpointer app, gint argc, gchar **argv) {
    return g_application_run(G_APPLICATION(app), argc, argv);
}
// Button
GtkButton* createButton(const gchar *label) {
    return (GtkButton*)gtk_button_new_with_label(label);
}
GtkButton* createButtonExpand(const gchar *label) {
    GtkButton* widget = createButton(label);
    setWidgetHorizntalExpand(widget, true);
    return widget;
}
// CheckButton
GtkCheckButton* createCheckButton(const gchar *label) {
    return label?
        (GtkCheckButton*)gtk_check_button_new_with_label(label):
        (GtkCheckButton*)gtk_check_button_new();
}
// Label
GtkLabel* createLabel(const gchar *label) {
    return (GtkLabel*)gtk_label_new(label);
}
// Entry Buffer
GtkEntryBuffer* createEntryBuffer() {
    return (GtkEntryBuffer*)gtk_entry_buffer_new(NULL, -1);
}
GtkEntryBuffer* createEntryBufferWithText(gchar *text) {
    return (GtkEntryBuffer*)gtk_entry_buffer_new(text, -1);
}

// Entry
GtkEntry* createEntry() {
    return (GtkEntry*)gtk_entry_new();
}
GtkEntry* createEntryWithEntryBuffer(GtkEntryBuffer *buffer) {
    GtkEntry *entry = createEntry();
    gtk_entry_set_buffer(entry, buffer);
    return entry;
}
GtkEntry* createEntryExpand() {
    GtkEntry* widget = createEntry();
    setWidgetHorizntalExpand(widget, true);
    return widget;
}
// Text
#if GTK_MAJOR_VERSION == 4
GtkText* createText(){
    return (GtkText*)gtk_text_new();
}
#endif
// TextBuffer -> TextView
GtkTextBuffer* createTextBuffer(GtkTextTagTable *table) {
    return (GtkTextBuffer*)gtk_text_buffer_new(table);
}
// TextView
GtkTextView* createTextView(){
    return (GtkTextView*)gtk_text_view_new();
}
GtkTextView* createTextViewWithTextBuffer(GtkTextBuffer* text_buffer) {
    GtkTextView* text_view = createTextView();
    gtk_text_view_set_buffer(text_view, text_buffer);
    return text_view;
}

// Box - Layout
GtkBox* createBox(GtkOrientation orientation, gint spacing) {
    return (GtkBox*)gtk_box_new(orientation, spacing);
}
// ComboBox
GtkComboBox* createComboBox() {
    return (GtkComboBox*)gtk_combo_box_new();
}
GtkComboBox* createComboBoxExpand(){
    GtkComboBox* widget = createComboBox();
    setWidgetHorizntalExpand(widget, true);
    return widget;
}
GtkComboBox* createComboBoxWithEntry() {
    return (GtkComboBox*)gtk_combo_box_new_with_entry();
}
GtkComboBox* createComboBoxWithModel(GtkTreeModel *model) {
    return (GtkComboBox*)gtk_combo_box_new_with_model(model);
}
GtkComboBox* createComboBoxWithModelUnref(GtkTreeModel *model) {
    GtkComboBox *comb = createComboBoxWithModel(model);
    objectUnref(model);
    return comb;
}
// Frame
GtkFrame* createFrame(const gchar *label) {
    return (GtkFrame*)gtk_frame_new(label);
}
// ProgreesBar
GtkProgressBar* createProgressBar() {
    return (GtkProgressBar*)gtk_progress_bar_new();
}

// HeaderBar
GtkHeaderBar* createHeaderBar() {
    return (GtkHeaderBar*)gtk_header_bar_new();
}

// ------------------------------------ Window decorations
void setWindowHeaderBar(gpointer window, gpointer bar) {
    gtk_window_set_titlebar(window, bar);
}
void setWindowTitle(gpointer window, const gchar *title) {
    gtk_window_set_title(GTK_WINDOW(window), title);
}
void setWindowSize(gpointer window, gint width, gint height) {
    gtk_window_set_default_size(GTK_WINDOW(window), width, height);
}
// Window
void setWindowTitleSize(gpointer window, const gchar *title, gint width, gint height) {
    setWindowTitle(window, title);
    setWindowSize(window, width, height);
}
GtkWindow* createWindowWithTitleSize(GtkApplication *app, const gchar *title, gint width, gint height) {
    GtkWidget *window = gtk_application_window_new(app);
    setWindowTitleSize(window, title, width, height);
    return (GtkWindow*)window;
}
void setWindowChild(gpointer window, gpointer widget) {

#if GTK_MAJOR_VERSION == 3
    gtk_container_add(window, widget);
#endif

#if GTK_MAJOR_VERSION == 4
    gtk_window_set_child(GTK_WINDOW(window), GTK_WIDGET(widget));
#endif

}

void showWindow(gpointer window){

#if GTK_MAJOR_VERSION == 3
    gtk_widget_show_all(window);
#endif

#if GTK_MAJOR_VERSION == 4
    gtk_widget_show(GTK_WIDGET(window));
    gtk_window_present(GTK_WINDOW(window));
#endif
    // gtk_window_set_modal(window, true);
}
void closeWindow(gpointer window) {
    gtk_window_close(GTK_WINDOW(window));
}

// Frame
void setFrameChild(gpointer frame, gpointer widget) {
#if GTK_MAJOR_VERSION == 3
    gtk_container_add(frame, widget);
#endif
#if GTK_MAJOR_VERSION == 4
    gtk_frame_set_child(GTK_FRAME(frame), GTK_WIDGET(widget));
#endif
}
GtkFrame* createFrameWithChild(const gchar *label, gpointer widget) {
    GtkFrame *frame = createFrame(label);
    setFrameChild(frame, widget);
    return frame;
}

// Button
void setButtonTooltipText(gpointer button, char *text) {
    // gtk_widget_set_tooltip_text(GTK_WIDGET(button), text);
    gtk_widget_set_tooltip_markup(button, text);
}

// ...
gpointer createWidgetTooltipText(gpointer widget, char *text) {
    gtk_widget_set_tooltip_markup(widget, text);
    return widget;
}

// ------------------------------------ Layout Manage
// 设置控件的展开对齐
void setWidgetHorizntalExpand(gpointer widget, gboolean expand){
    gtk_widget_set_hexpand(widget, expand);
}
void setWidgetVerticalExpand(gpointer widget, gboolean expand){
    gtk_widget_set_vexpand(widget, expand);
}
void setWidgetHorizntalAlign(gpointer widget, WidgetAlign align) {
    gtk_widget_set_halign(widget, (GtkAlign)align);
}
void setWidgetVerticalAlign(gpointer widget, WidgetAlign align) {
    gtk_widget_set_valign(widget, (GtkAlign)align);
}
gpointer createWidgetHorizntalExpand(gpointer widget, gboolean expand){
    setWidgetHorizntalExpand(widget,expand);
    return widget;
}
gpointer createWidgetVerticalExpand(gpointer widget, gboolean expand){
    setWidgetVerticalExpand(widget,expand);
    return widget;
}
gpointer createWidgetHorizntalExpandWithFunc(createFunc func, gboolean expand) {
    return createWidgetHorizntalExpand(func(), expand);
}
gpointer createWidgetVerticalExpandWithFunc(createFunc func, gboolean expand) {
    return createWidgetVerticalExpand(func(), expand);
}

// 设置控件的起始边距
void setWidgetMargin(gpointer box, gint start, gint end, gint top, gint bottom) {
    gtk_widget_set_margin_start(GTK_WIDGET(box), start);
    gtk_widget_set_margin_end(GTK_WIDGET(box), end);
    gtk_widget_set_margin_top(GTK_WIDGET(box), top);
    gtk_widget_set_margin_bottom(GTK_WIDGET(box), bottom);
}
void setWidgetFullMargin(gpointer widget, gint margin) {
    setWidgetMargin(widget, margin, margin, margin, margin);
}

// Box - Layout
GtkBox* createBoxWithOrientation(GtkOrientation orientation, gint spacing) {
    return createBox(orientation, spacing);
}
GtkBox* createBoxWithHorizntal(gint spacing) {
    return createBoxWithOrientation(GTK_ORIENTATION_HORIZONTAL, spacing);
}
GtkBox* createBoxWithVertical(gint spacing) {
    return createBoxWithOrientation(GTK_ORIENTATION_VERTICAL, spacing);
}
GtkBox* createBoxWithHorizntalMargin(gint spacing, gint margin) {
    GtkBox *box = createBoxWithHorizntal(spacing);
    setBoxFullMargin(box, margin);
    return box;
}
GtkBox* createBoxWithVerticalMargin(gint spacing, gint margin) {
    GtkBox *box = createBoxWithVertical(spacing);
    setBoxFullMargin(box, margin);
    return box;
}

// ┌──────────────────────────────────────────────────────────────────────────────┐
// │ va_list     TYPE以保存有关变量参数的信息(TYPE)。                                  │
// │ va_start    初始化变量参数列表(宏)。                                             │
// │ va_arg      检索下一个参数(宏)                                                  │
// │ va_end      使用变量参数列表(宏)结束。                                           │
// │ vsprintf    将格式化数据从变量参数列表写入字符串(函数)                              │
// └──────────────────────────────────────────────────────────────────────────────┘
#define convValist(target, source, start) va_list vlist; \
        va_start(vlist, start);                         \
        target(source, start, vlist);                   \
        va_end(vlist);

static void boxAppendValist(GtkBox *box, gpointer child, va_list vlist) {
    while (child) {
        boxAppend(box, child);
        child = va_arg(vlist, gpointer);
    }
}
void boxAppend(GtkBox *box, gpointer widget) {

#if GTK_MAJOR_VERSION == 3
    gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(widget));
#endif

#if GTK_MAJOR_VERSION == 4
    gtk_box_append(box, GTK_WIDGET(widget));
#endif
}
void boxAppends(GtkBox *box, gpointer chiled, ...) {
    va_list vlist;
    va_start(vlist, chiled);
    boxAppendValist(box, chiled, vlist);
    va_end(vlist);
}
GtkBox* createBoxWithHorizntalAppends(gint spacing, gpointer chiled, ...) {
    GtkBox *box = createBoxWithHorizntal(spacing);
    va_list vlist;
    va_start(vlist, chiled);
    boxAppendValist(box, chiled, vlist);
    va_end(vlist);
    return box;
}
GtkBox* createBoxWithVerticalAppends(gint spacing, gpointer chiled, ...) {
    GtkBox *box = createBoxWithVertical(spacing);
    va_list vlist;
    va_start(vlist, chiled);
    boxAppendValist(box, chiled, vlist);
    va_end(vlist);
    return box;
}

// Box - sma
GtkBox* createBoxWithHorizntalMarginAppends(gint spacing, gint margin, gpointer chiled, ...) {
    GtkBox *box = createBoxWithHorizntalMargin(spacing, margin);
    convValist(boxAppendValist, box, chiled)
    return box;    
}
GtkBox* createBoxWithVerticalMarginAppends(gint spacing, gint margin, gpointer chiled, ...) {
    GtkBox *box = createBoxWithVerticalMargin(spacing, margin);
    convValist(boxAppendValist, box, chiled)
    return box;
}
// Box - smaa
GtkBox* createBoxWithHorizntalMarginAlignAppends(gint spacing, gint margin, WidgetAlign align, gpointer chiled, ...) {
    GtkBox *box = createBoxWithHorizntalMargin(spacing, margin);
    convValist(boxAppendValist, box, chiled)
    setWidgetHorizntalAlign(box, align);
    return box;
}
GtkBox* createBoxWithVerticalMarginAlignAppends(gint spacing, gint margin, WidgetAlign align, gpointer chiled, ...) {
    GtkBox *box = createBoxWithHorizntal(spacing);
    convValist(boxAppendValist, box, chiled)
    setWidgetVerticalAlign(box, align);
    return box;
}

GtkBox* createBoxWithHorizntalMarginExpandAppends(gint spacing, gint margin, gboolean expand, gpointer chiled, ...){
    GtkBox *box = createBoxWithHorizntalMargin(spacing, margin);
    convValist(boxAppendValist, box, chiled)
    setWidgetHorizntalExpand(box, expand);
    return box;
}
GtkBox* createBoxWithVerticalMarginExpandAppends(gint spacing, gint margin, gboolean expand, gpointer chiled, ...){
    GtkBox *box = createBoxWithHorizntalMargin(spacing, margin);
    convValist(boxAppendValist, box, chiled)
    setWidgetVerticalExpand(box, expand);
    return box;
}

// Separator
GtkSeparator* createSeparatorWithOrientation(GtkOrientation orientaion) {
    return (GtkSeparator*)gtk_separator_new(orientaion);
}
GtkSeparator* createSeparatorWithHorizntal() {
    return createSeparatorWithOrientation(GTK_ORIENTATION_HORIZONTAL);
}
GtkSeparator* createSeparatorWithVertical() {
    return createSeparatorWithOrientation(GTK_ORIENTATION_VERTICAL);
}

// ComboBox
void setComboBoxActive(GtkComboBox *combo_box, int index) {
    gtk_combo_box_set_active(combo_box, index);
}
gboolean getComboBoxActiveIter(GtkComboBox *combo_box, GtkTreeIter *iter) {
    return gtk_combo_box_get_active_iter(combo_box, iter);
}
// gchar* getComboBoxActiveText(GtkComboBox *comb) {
//     gtk_combo_box_get_entry_text_column(comb, )
// }

// ------------------------------------ TreeModel
// #define createTreeModelFunc(func) GtkTreeModel* func(void)
// typedef GtkTreeModel*(*createTreeModel)(void);
// #define createTreeModelWithFunc(model, createTreeModel) GtkTreeModel* model = createTreeModel()
// #define treeModelWithFunc(model, createTreeModel) model = createTreeModel()

// 扩展：ComboBox Utils 
GtkComboBox* createComboBoxWithModelFuncUnref(createTreeModel func) {
    GtkComboBox *comb = createComboBoxWithModelUnref(func());
    return comb;
}
GtkComboBox* createComboBoxWithModelFuncUnrefActive(createTreeModel func, int index) {
    GtkComboBox *comb = createComboBoxWithModelFuncUnref(func);
    setComboBoxActive(comb, index);
    return comb;
}

// GtkTreeModel* createTreeModelWithComboBox(GtkComboBox *combo) {
//     return gtk_combo_box_get_model(combo);
// }

// ------------------------------------ TreePath
// 返回iter引用的新创建的GtkTreePath。
// 应该使用gtk_tree_path_free()释放该路径。
// GtkTreePath *gtk_tree_model_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter)

GtkTreePath* createTreePath() {
    return gtk_tree_path_new();
}
GtkTreePath* createTreePathWithTreeModel(GtkTreeModel *tree_model, GtkTreeIter *iter) {
    return gtk_tree_model_get_path(tree_model, iter);
}
void destroyTreePath(GtkTreePath *path) {
    gtk_tree_path_free(path);
}
// 返回路径的当前索引。
// 这是一个整数数组，每个整数表示树中的一个节点。这个值不应该被释放。
// 数组的长度可以通过gtk_tree_path_get_depth()获得。
// int *gtk_tree_path_get_indices(GtkTreePath *path)
int *treePathGetIndices(GtkTreePath *path) {
    return gtk_tree_path_get_indices(path);
}

// ------------------------------------ Renderer
GtkCellRendererPixbuf* createCellRendererPixbuf() {
    return (GtkCellRendererPixbuf*)gtk_cell_renderer_pixbuf_new();
}
GtkCellRendererText* createCellRendererText() {
    return (GtkCellRendererText*)gtk_cell_renderer_text_new();
}
GtkCellRendererProgress* createCellRendererProgress() {
    return (GtkCellRendererProgress*)gtk_cell_renderer_progress_new();
}
GtkCellRendererSpin* createGtkCellRendererSpin() {
    return (GtkCellRendererSpin*)gtk_cell_renderer_spin_new();
}
// gtk_cell_renderer_new()


// ------------------------------------ Cell Layout
// Gtk.CellLayout.pack_start
// 将单元格打包到cell_layout的开头。
// 如果expand为FALSE，则单元格分配的空间不会超过它所需的空间。
// 任何未使用的空间被均匀地分配到扩展为TRUE的单元格之间。
// 注意，不支持重用相同的单元格呈现程序。

// void (*GtkCellLayoutDataFunc)(GtkCellLayout *, GtkCellRenderer *,GtkTreeModel *, GtkTreeIter *, gpointer)
// #define createCellLayoutDataFunc(func) void func(GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
// #define createCellLayoutDataFunc(func) gboolean func(void)
// typedef gboolean(*createCellLayoutData)(void);

void setCellLayoutExpand(gpointer widget, gpointer renderer, const char *attributes, gint colume, GtkCellLayoutDataFunc func, gboolean expand) {
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), GTK_CELL_RENDERER(renderer), expand);
// 将参数列表中的属性设置为cell_layout的属性。
// 更多细节请参见gtk_cell_layout_add_attribute()。
// 属性应该按属性/列顺序排列，如gtk_cell_layout_add_attribute(), 删除所有现有属性，并用新属性替换。
    gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), GTK_CELL_RENDERER(renderer), attributes, colume, NULL);
// 这个函数应该设置cell_layout的单元格渲染器的值。
// gtk_cell_layout_set_cell_data_func(GtkCellLayout *cell_layout, GtkCellRenderer *cell, GtkCellLayoutDataFunc func, gpointer func_data, GDestroyNotify destroy)
    gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(widget), GTK_CELL_RENDERER(renderer), func, NULL, NULL);
}
// 设置单元格处理器，
void setCellLayout(gpointer widget, gpointer renderer, const char *attributes, gint colume, GtkCellLayoutDataFunc func, gboolean expand) {
    setCellLayoutExpand(widget, renderer, attributes, colume, func, expand);
}

// GtkTreeViewRowSeparatorFunc
// #define createTreeViewRowSeparatorFunc(func) gboolean func(GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)

// 扩展：ComboBox Utils 
// Usage：
// 设置行分隔符函数，该函数用于确定是否应将行绘制为分隔符。
// 如果行分隔符函数为NULL，则不绘制分隔符。这是默认值。
// func 应该以 createTreeViewRowSeparatorFunc 宏创建
void setComboBoxRowSeparatorFunc(gpointer combo, GtkTreeViewRowSeparatorFunc func, gpointer data, GDestroyNotify destroy) {
    gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(combo), func, data, destroy);
}

// ------------------------------------ List Store
// 创建可存储列表
// #define createListStore(n, argc...) gtk_list_store_new(n, ##argc)
// extern void gtk_list_store_append(GtkListStore *list_store, GtkTreeIter *iter)
void listStoreAppend(GtkListStore* list_store, GtkTreeIter *iter) {
    gtk_list_store_append(list_store, iter);
}
// #define listStoreAppend(l, ) gtk_list_store_append()

// 设置iter引用的行中一个或多个单元格的值。
// 变量参数列表应该包含整型列号，每个列号后面跟着要设置的值。
// 列表以-1结束。例如，要将类型G_TYPE_STRING为“Foo”的列0设置为“Foo”，
// 您可以编写gtk_list_store_set (store, iter, 0, "Foo", -1)

// void gtk_list_store_set(GtkListStore *list_store, GtkTreeIter *iter, ...)
// #define listStoreSet(list_store, iter, argc...) gtk_list_store_set(list_store, iter, ##argc)

// GtkListStore* createListStore(int n_columns, ...) {
//     return gtk_list_store_new(n_columns, ...);
// }


// ------------------------------------ Tree Store
// 创建可存储树
void treeStoreAppend(GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent) {
    gtk_tree_store_append(tree_store, iter, parent);
}

// ------------------------------------ Utilities Tool

// Timer
// gboolean (*GSourceFunc)(gpointer)
// #define createGSourceFunc(func) gboolean func(gpointer source)
// #define createGSourceObjectFunc(func, type) gboolean func(type *source)
/**
 * 定时器统一管理部分，负责创建，销毁定时器
 * createTimerMilliSecond: 创建毫秒级定时器
 * createTimerSecond: 创建秒级定时器
 * timerStarted: 判断定时器是否已启动
 * stopTimer: 停止并释放定时器
 */
guint createTimerMilliSecond(guint interval, gpointer handle, gpointer data) {
    return g_timeout_add(interval, (GSourceFunc)handle, data);
}
guint createTimerSecond(guint interval, gpointer handle, gpointer data) {
    return g_timeout_add_seconds(interval, (GSourceFunc)handle, data);
}
gboolean timerStarted(guint *timer) {
    if (*timer > 0) return true;
    return false;
}
static void cleanTimer(guint *timer) {
    *timer = 0;
}
static gboolean destroyTimer(guint *timer) {
    return g_source_remove(*timer);
}
gboolean stopTimer(guint *timer) {
    if (timerStarted(timer)) destroyTimer(timer);
    cleanTimer(timer);
    return true;
}

// ------------------------------------ Clipboard

// 扩展：Entry Utils
guint16 entryGetTextLength(GtkEntry *entry) {
    return gtk_entry_get_text_length(entry);
}
const gchar* entryGetText(GtkEntry *entry) {
#if GTK_MAJOR_VERSION == 3
    return gtk_entry_get_text(entry);
#endif
#if GTK_MAJOR_VERSION == 4
    return gtk_editable_get_text(GTK_EDITABLE(entry));
#endif
}
void entrySetText(GtkEntry *entry, const char *text){
#if GTK_MAJOR_VERSION == 3
    gtk_entry_set_text(entry, text);
#endif
#if GTK_MAJOR_VERSION == 4
    gtk_editable_set_text(GTK_EDITABLE(entry), text);
#endif
}

// 获取Clipboard
GdkClipboard* createClipboardWithWidget(gpointer widget) {
#if GTK_MAJOR_VERSION == 3
    return gtk_widget_get_clipboard(widget, NULL);
#endif

#if GTK_MAJOR_VERSION == 4
    return gtk_widget_get_clipboard(GTK_WIDGET(widget));
#endif
}
// 设置Clipboard
void setClipboardText(GdkClipboard *clipboard, const gpointer text){
#if GTK_MAJOR_VERSION == 4
    gdk_clipboard_set_text(clipboard, text);
#endif
}

// GAsyncResult
// GAsyncReadyCallback
// void (*GAsyncReadyCallback) (GObject *source_object, GAsyncResult *res, gpointer user_data)
// typedef GAsyncReadyCallback GAsyncReadyCallbackObject;
// #define createGAsyncReadyCallbackFunc(func) void func(GObject *source_object, GAsyncResult *res, gpointer user_data)
// #define createGAsyncReadyCallbackObjectFunc(func, type) void func(GObject *source_object, GAsyncResult *result, type *user_data)
// #define createGAsyncReadyCallbackSourceObjectFunc(func, source, type) void func(source *source_object, GAsyncResult *result, type *user_data)

// int gdk_clipboard_read_text_finish(GdkClipboard *clipboard, GAsyncResult *result, GError **error)
gchar* clipboardReadTextFinish(GdkClipboard *clipboard, GAsyncResult *result, GError **error) {

#if GTK_MAJOR_VERSION == 3

#endif

#if GTK_MAJOR_VERSION == 4
    return gdk_clipboard_read_text_finish(clipboard, result, error); 
#endif
}

// void gdk_clipboard_read_text_async(GdkClipboard *clipboard, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
void clipboardReadTextAsync(GdkClipboard *clipboard, GCancellable *cancellable, AsyncReadyCallbackObject callback, gpointer user_data) {

#if GTK_MAJOR_VERSION == 3
    gtk_clipboard_request_text(clipboard, callback, user_data);
#endif

#if GTK_MAJOR_VERSION == 4
    return gdk_clipboard_read_text_async(clipboard, cancellable, (GAsyncReadyCallbackObject)callback, user_data);
#endif
}


// PixBuf
GdkPixbuf* createPixbuferFromFile(const char *filename, GError **error) {
    return gdk_pixbuf_new_from_file(filename, error);
}

// Image
GtkImage* createImage() {
    return (GtkImage*)gtk_image_new();
}
GtkImage* createImageFromFile(const char *filename) {
    return (GtkImage*)gtk_image_new_from_file(filename);
}
GtkImage* createImageFromPixbuf(GdkPixbuf *pixbuf) {
    return (GtkImage*)gtk_image_new_from_pixbuf(pixbuf);
}

#if GTK_MAJOR_VERSION == 4
// Emoji
GtkEmojiChooser* createEmojiChooser() {
    return (GtkEmojiChooser*)gtk_emoji_chooser_new();
}
#endif


// Dialog
GtkDialog* createDialog() {
    return (GtkDialog*)gtk_dialog_new();
}
GtkBox* dialogGetContentArea(GtkDialog *dialog) {
    return (GtkBox*)gtk_dialog_get_content_area(dialog);
}